#region Using

using System;
using System.Collections.Generic;

#endregion

namespace BlogEngine.Core
{
    /// <summary>
    /// A page is much like a post, but is not part of the blog chronology 
    /// and is more static in nature.
    /// <remarks>
    /// Pages can be used for "About" pages or other static information.
    /// </remarks>
    /// </summary>
	public sealed class Page : PublishableBase<Page>, IComparable<Page>
    {

        #region Constructor

        /// <summary>
        /// The contructor sets default values.
        /// </summary>
        public Page() :base()
        {
        }

        #endregion

        #region Properties

        private string _Keywords = string.Empty;
        /// <summary>
        /// Gets or sets the Keywords or the object.
        /// </summary>
        public string Keywords
        {
            get { return _Keywords; }
            set
            {
                if (_Keywords != value) MarkChanged("Keywords");
                _Keywords = value;
            }
        }

        private Guid _Parent = Guid.Empty;
        /// <summary>
        /// Gets or sets the parent of the Page. It is used to construct the 
        /// hierachy of the pages.
        /// </summary>
        public Guid Parent
        {
            get { return _Parent; }
            set
            {
                if (_Parent != value) MarkChanged("Parent");
                _Parent = value; 
            }
        }

        private bool _IsFrontPage;
        /// <summary>
        /// Gets or sets whether or not this page should be displayed on the front page.
        /// </summary>
        public bool IsFrontPage
        {
            get { return _IsFrontPage; }
            set
            {
                if (_IsFrontPage != value) MarkChanged("IsFrontPage");
                _IsFrontPage = value; 
            }
        }

        private bool _ShowInList;
        /// <summary>
        /// Gets or sets whether or not this page should be in the sitemap list.
        /// </summary>
        public bool ShowInList
        {
            get { return _ShowInList; }
            set
            {
              if (_ShowInList != value) MarkChanged("ShowInList");
              _ShowInList = value; 
            }
        }

        /// <summary>
        /// Returns the front page if any is available.
        /// </summary>
        public static Page GetFrontPage()
        {
            foreach (Page page in PublishableBase<Page>.Items)
            {
                if (page.IsFrontPage)
                {
                    return page;
                }
            }

            return null;
        }
        
        /// <summary>
        /// Returns a list of pages for a parent 
        /// </summary>
        /// <param name="parent"></param>
        /// <returns></returns>
        public static List<Page> GetChildPages(Page parent)
        {
            List<Page> list = new List<Page>();

            foreach (Page page in PublishableBase<Page>.Items)
            {
                if (page.Parent == parent.Id)
                {
                    list.Add(page);
                }
            }

            return list;
        }

        #endregion

        #region Base overrides

        /// <summary>
        /// returns the prefix to use for URL rewriting
        /// </summary>
        /// <returns></returns>
        protected override string RelativeLinkPrefix()
        {
            return "page/";
        }
        /// <summary>
        /// returns the prefix to use for permalink URL rewriting
        /// </summary>
        /// <returns></returns>
        protected override string PermaLinkPrefix()
        {
            return "page";
        }

		/// <summary>
		/// Validates the item instance.
		/// </summary>
		/// <remarks>
		/// Each derived class should override this and ensure they call base.ValidationRules()
		/// to get a composite set of rules.
		///</remarks>
		protected override void ValidationRules()
		{
			AddRule("Content", "Content must be set", String.IsNullOrEmpty(Content));
			base.ValidationRules();
		}

        #endregion

        #region IComparable<Page> Members

        /// <summary>
        /// Compares the current object with another object of the same type.
        /// </summary>
        /// <remarks>
        /// Sort Order is: Order (ascending) then Title (ascending)
        /// </remarks>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// A 32-bit signed integer that indicates the relative order of the objects being compared. 
        /// The return value has the following meanings: Value Meaning Less than zero This object is 
        /// less than the other parameter.Zero This object is equal to other. Greater than zero This object is greater than other.
        /// </returns>
        public int CompareTo(Page other)
        {
            return CompareOrderAndTitle(this.Order, DateTime.MinValue, this.Title, other.Order, DateTime.MinValue, other.Title);
        }

        #endregion

		#region Data Access

		static internal BlogEngine.Core.Provider.Interfaces.IPages PageProvider = BlogEngine.Core.Provider.BlogService.Provider.GetInterface<BlogEngine.Core.Provider.Interfaces.IPages>();

		protected override void DataDelete()
		{
			//make sure any child pages have the parent removed.
			foreach (Page child in Page.GetChildPages(this))
			{
				child.Parent = Guid.Empty;
				child.Save();
			}

			PageProvider.Delete(this);
		}

		protected override void DataInsert()
		{
			PageProvider.Insert(this);
		}

		protected override Page DataSelect(Guid id)
		{
			return PageProvider.Select(id);
		}

		protected override void DataUpdate()
		{
			PageProvider.Update(this);
		}

		private static int Dummy = OverrideOnLoad();

		private static int OverrideOnLoad()
		{
			OnLoad = PageProvider.Fill;
			return 0;
		}

		#endregion

		/// <summary>
		/// Gets the Pages.
		/// </summary>
		/// <value>The Pages.</value>
		public static List<Page> Pages
		{
			get
			{
				return Items;
			}
		}

		/// <summary>
		/// Returns a page based on the specified id.
		/// </summary>
		public static Page GetPage(Guid id)
		{
			return GetById(id);
		}

      }
}
